/**
 **********************************************************************************************************************
 * @file    menu_frame.h
 * @brief   该文件提供菜单框架所有函数原型
 **********************************************************************************************************************
 */

#ifndef MMI_MENU_H
#define MMI_MENU_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

#ifdef __cplusplus
extern "C"
{
#endif

/* 启用快捷菜单选项进入功能 */
#define MMI_MENU_USE_SHORTCUT 1
/* 多级菜单深度, 4级：0,1,2,3,4 */
#define MMI_MENU_MAX_DEPTH 5
/* 菜单支持的最大选项数目 */
#define MMI_MENU_MAX_NUMBER 10

  typedef union
  {
    void *pVoid;       /*!< 通用指针(目的消除编译警告) */
    size_t textId;     /*!< 文本ID */
    char *pTextString; /*!< 文本字符串 */
  } UN_MENU_DESC;

  /**
   * @brief      单个选项信息
   */
  typedef struct
  {
    UN_MENU_DESC uMenuDesc; /*!< 该选项的描述 */
    void *pExtendData;      /*!< 该选项注册时的扩展数据 */
  } ST_MENU_ITEM_INFO;

  typedef struct
  {
    uint16_t code;
    uint16_t value;
  } ST_KEY_INFO;

  typedef void (*PF_MENU_TASK_CB)(const ST_KEY_INFO *pKeyInfo, const ST_MENU_ITEM_INFO *pItemInfo);
  typedef void (*PF_MENU_LOAD_CB)(const ST_MENU_ITEM_INFO *pItemInfo);
  typedef void (*PF_MENU_ENTER_CB)(const ST_MENU_ITEM_INFO *pItemInfo);
  typedef void (*PF_MENU_EXIT_CB)(const ST_MENU_ITEM_INFO *pItemInfo);

  /**
   * @brief      单个选项带菜单列表等信息
   */
  typedef struct
  {
    uint8_t itemsNum;                                 /*!< 当前菜单中选项的总数目 */
    uint8_t selectItem;                               /*!< 当前菜单中被选中的选项 */
    uint8_t showBaseItem;                             /*!< 当前菜单首个显示的选项 */
    UN_MENU_DESC uMenuDesc;                           /*!< 当前菜单的描述 */
    void *pExtendData;                                /*!< 当前菜单注册时的扩展数据 */
    UN_MENU_DESC uItemsListDesc[MMI_MENU_MAX_NUMBER]; /*!< 当前菜单中选项列表的描述 */
    void *pItemsListExtendData[MMI_MENU_MAX_NUMBER];  /*!< 当前菜单中选项列表注册时的扩展数据 */
  } ST_MENU_SHOW;

  typedef void (*PF_MENU_SHOW_CB)(ST_MENU_SHOW *ptShowInfo);

  /**
   * @brief 菜单信息注册结构体
   */
  typedef struct
  {
    UN_MENU_DESC uMenuDesc;            /*!< 当前菜单的描述 */
    PF_MENU_ENTER_CB pfnEnterCallback; /*!< 当前菜单选项进入时(从父菜单进入)需要执行一次的函数, 为NULL不执行 */
    PF_MENU_EXIT_CB pfnExitCallback;   /*!< 当前菜单选项进入后退出时(退出至父菜单)需要执行一次的函数, 为NULL不执行 */
    PF_MENU_LOAD_CB pfnLoadCallback;   /*!< 当前菜单选项每次加载时(从父菜单进入或子菜单退出)需要执行一次的函数, 为NULL不执行 */
    PF_MENU_TASK_CB pfnTaskCallback;   /*!< 当前菜单选项的周期调度函数 */
    void *pExtendData;                 /*!< 当前选项的菜单显示效果函数扩展数据入参, 可自行设置该内容 */
  } ST_MENU_LIST, ST_MENU_CFG;

/**
 * @brief  单个菜单选项定义
 * @param  title    菜单选项描述
 * @param  cb_enter 当前菜单选项进入时(从父菜单进入)需要执行一次的函数, 为NULL不执行
 * @param  cb_exit  当前菜单选项进入后退出时(退出至父菜单)需要执行一次的函数, 为NULL不执行
 * @param  cb_load  当前菜单选项每次加载时(从父菜单进入或子菜单退出)需要执行一次的函数, 为NULL不执行
 * @param  cb_task   当前菜单选项的周期调度函数
 * @param  ext_data 当前选项的菜单显示效果函数扩展数据入参, 可自行设置该内容
 */
#define MMI_MENU_ITEM_BIND(title, cb_enter, cb_exit, cb_load, cb_task, ext_data) \
  {                                                                               \
      .uMenuDesc = {.pVoid = (void *)title},                                      \
      .pfnEnterCallback = cb_enter,                                               \
      .pfnExitCallback = cb_exit,                                                 \
      .pfnLoadCallback = cb_load,                                                 \
      .pfnTaskCallback = cb_task,                                                  \
      .pExtendData = ext_data}

// 计算得到菜单列表元素数目
#define MMI_GET_MENU_NUM(X) (sizeof(X) / sizeof(ST_MENU_LIST))

  /* 主菜单操作 */
  extern int MMI_MainMenuEnter(void);
  extern int MMI_MainMenuExit(void);

  /* 菜单初始化和反初始化 */
  extern int MMI_MenuInit(ST_MENU_CFG *pMainMenu);
  extern int MMI_MenuDeinit(void);
  extern int MMI_MenuBind(ST_MENU_LIST *pMenuList, uint8_t menuNum, PF_MENU_SHOW_CB pfnShowCallback);

  /* 菜单选项显示时需要使用的功能扩展函数 */
  extern int MMI_MenuLimitShowListNumber(ST_MENU_SHOW *ptMenuShow, uint8_t *pShowNum);
  extern int MMI_MenuQueryParentMenu(ST_MENU_SHOW *ptMenuShow, uint8_t level);

  /* 菜单操作 */
  extern int MMI_MenuReset(void);
  extern int MMI_MenuEnter(void);
  extern int MMI_MenuExit(bool isReset);
  extern int MMI_MenuSelectPrev(bool isAllowRoll);
  extern int MMI_MenuSelectNext(bool isAllowRoll);
  extern int MMI_MenuSelect(uint8_t selectItem);
  extern int MMI_MenuShortcutEnter(bool isAbsolute, uint8_t deep, ...);

  /* 菜单轮询处理任务 */
  extern int MMI_MenuTask(const ST_KEY_INFO *pKeyInfo);

#ifdef __cplusplus
}
#endif

#endif // MENU_H
